package controllers

import (
	"fmt"
	"goblog/app/models/article"
	"goblog/app/requests"
	"goblog/pkg/auth"
	"goblog/pkg/config"
	"goblog/pkg/logger"
	"goblog/pkg/route"
	"goblog/pkg/types"
	"goblog/pkg/view"
	"goblog/policies"
	"net/http"
)

// ArticlesController 博文管理
type ArticlesController struct {
	BaseController // 相当于继承
}

// Show 详情页
func (ac *ArticlesController) Show(w http.ResponseWriter, r *http.Request) {

	// 1. 执行查询于语句，返回一个结果集
	id := route.GetRouteVariable("id", r)
	_article, err := article.Get(id)

	if err != nil {
		ac.ResponseForSQLError(w, err)
	} else {
		fmt.Println(policies.CanModifyArticle(_article))
		// 2. 加载模板
		view.Render(w, view.D{
			"Article":          _article,
			"CanModifyArticle": policies.CanModifyArticle(_article),
		}, "articles.show", "articles._article_meta")
	}
}

// Index 文章列表頁
func (ac *ArticlesController) Index(w http.ResponseWriter, r *http.Request) {

	// 1. 执行查询于语句，返回一个结果集
	articles, PagerData, err := article.GetPage(r, config.GetInt("pagination.perpage"))
	logger.LogError(err)

	if err != nil {
		ac.ResponseForSQLError(w, err)
	} else {
		// 2. 加载模板
		view.Render(w, view.D{
			"Articles":  articles,
			"PagerData": PagerData,
		}, "articles.index", "articles._article_meta")
	}
}

// Create 保存文章表单页
func (*ArticlesController) Create(w http.ResponseWriter, r *http.Request) {

	view.Render(w, view.D{
		"Article":    article.Article{},
		"Error":      nil,
	}, "articles.create", "articles._form_field")
}

// Store 存储文章
func (*ArticlesController) Store(w http.ResponseWriter, r *http.Request) {

	_article := article.Article{
		Title:      r.PostFormValue("title"),
		Body:       r.PostFormValue("body"),
		UserID:     auth.User().Id,
		CategoryID: types.StringToUint64(r.PostFormValue("category_id")),
	}
	errors := requests.ValidateArticleForm(_article)

	// utf8.RuneCountInString(title) 中文字符 1 个就是 1
	// len 一个中文字符 3 字节
	if len(errors) == 0 {
		_ = _article.Create()
		if _article.Id > 0 {
			indexUrl := route.Name2URL("articles.show", "id", _article.GetStringID())
			http.Redirect(w, r, indexUrl, http.StatusFound)
		} else {
			w.WriteHeader(http.StatusInternalServerError)
			_, _ = fmt.Fprint(w, "创建文章失败，请联系管理员~")
		}

	} else {
		view.Render(w, view.D{
			"Article":    _article,
			"Errors":     errors,
		}, "articles.create", "articles._form_field")
	}
}

// Edit 修改文章表单
func (ac *ArticlesController) Edit(w http.ResponseWriter, r *http.Request) {

	// 1. 获取 URL 参数
	id := route.GetRouteVariable("id", r)
	_article, err := article.Get(id)

	if err != nil {
		ac.ResponseForSQLError(w, err)
	} else {

		if !policies.CanModifyArticle(_article) {
			ac.ResponseForUnauthorized(w, r)
		} else {
			// 4. 读取成功，显示文章
			view.Render(w, view.D{
				"Article": _article,
				"Error":   nil,
			}, "articles.edit", "articles._form_field")
		}
	}
}
func (ac *ArticlesController) Update(w http.ResponseWriter, r *http.Request) {
	// 1. 获取 URL 的参数
	// 2. 读取对应的文章数据
	id := route.GetRouteVariable("id", r)
	_article, err := article.Get(id)

	// 3. 如果出现错误
	if err != nil {
		ac.ResponseForSQLError(w, err)
	} else {
		// 4. 未出现错误

		if !policies.CanModifyArticle(_article) {
			ac.ResponseForUnauthorized(w, r)
			return
		}

		// 4.1 表单验证
		_article.Title = r.PostFormValue("title")
		_article.Body = r.PostFormValue("body")
		_article.CategoryID = types.StringToUint64(r.PostFormValue("category_id"))

		errors := requests.ValidateArticleForm(_article)

		if len(errors) == 0 {
			// 4.2 验证通过，更新数据

			rowsAffected, err := _article.Update()

			if err != nil {
				logger.LogError(err)
				w.WriteHeader(http.StatusInternalServerError)
				_, _ = fmt.Fprint(w, "500 服务器内部错误~")
				return
			}

			if rowsAffected > 0 {
				showURL := route.Name2URL("articles.show", "id", id)
				http.Redirect(w, r, showURL, http.StatusFound)
			} else {
				_, _ = fmt.Fprint(w, "您没有做任何更改~")
			}

		} else {

			//表单验证不通过，显示错误信息
			view.Render(w, view.D{
				"Article": _article,
				"Error":   errors,
			}, "articles.edit", "articles._form_field")
		}
	}
}

// Delete 删除文章
func (ac *ArticlesController) Delete(w http.ResponseWriter, r *http.Request) {
	// 1. 获取 URL 参数
	id := route.GetRouteVariable("id", r)
	// 2. 读取对应的文章数据
	_article, err := article.Get(id)

	// 3. 如果结果出错
	if err != nil {
		ac.ResponseForSQLError(w, err)
	} else {

		if !policies.CanModifyArticle(_article) {
			ac.ResponseForUnauthorized(w, r)
			return
		}

		// 4. 未出现错误，执行删除操作
		affected, err := _article.Delete()
		if err != nil {
			// 应该是 SQL 报错了
			logger.LogError(err)
			w.WriteHeader(http.StatusInternalServerError)
			_, _ = fmt.Fprint(w, "500 服务器内部错误")
		} else {
			// 未发生错误
			if affected > 0 {
				// 重定向到文章列表
				indexURL := route.Name2URL("articles.index")
				http.Redirect(w, r, indexURL, http.StatusFound)
			} else {
				w.WriteHeader(http.StatusNotFound)
				_, _ = fmt.Fprint(w, "404 未找到文章~")
			}
		}
	}
}
